package com.pengshun.modules.api.order.service.impl;

import com.pengshun.modules.aliyun.OosPush;
import com.pengshun.modules.api.coal.repository.MerchantRepository;
import com.pengshun.modules.api.coal.repository.UserRepository;
import com.pengshun.modules.api.coal.util.CommonUtil;
import com.pengshun.modules.api.mapper.OrderMapper;
import com.pengshun.modules.api.mapper.PsUserInComRecordMapper;
import com.pengshun.modules.api.mapper.SystemMapper;
import com.pengshun.modules.api.order.service.dto.IncomeRecordDto;
import com.pengshun.modules.api.order.service.dto.PayResult;
import com.pengshun.modules.api.order.service.mapstruct.IncomeRecordTodo;
import com.pengshun.modules.api.order.service.mapstruct.MerchantOrderTodo;
import com.pengshun.modules.api.pay.service.WechatPayService;
import com.pengshun.modules.api.system.service.dto.AddresDto;
import com.pengshun.modules.api.transport.repository.TransportSettlementRepository;
import com.pengshun.modules.api.user.repository.IncomeRecordRepository;
import com.pengshun.modules.api.user.repository.IncomeRepository;
import com.pengshun.modules.api.user.repository.OrderPayRecordRepository;
import com.pengshun.modules.api.coal.repository.MerchantCoalRepository;
import com.pengshun.modules.api.order.repository.MerchantOrderRepository;
import com.pengshun.modules.api.order.service.BuyUserOrderService;
import com.pengshun.modules.api.order.service.dto.MerchantOrderDto;
import com.pengshun.modules.common.AuthenticationStatus;
import com.pengshun.modules.common.BaseResult;
import com.pengshun.modules.common.BillType;
import com.pengshun.modules.common.OrderCommon;
import com.pengshun.modules.domain.*;
import lombok.RequiredArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

@Service
@RequiredArgsConstructor
public class BuyUserOrderServiceImpl implements BuyUserOrderService {


    private final MerchantCoalRepository merchantCoalRepository;

    private final MerchantOrderRepository merchantOrderRepository;

    private final MerchantOrderTodo merchantOrderTodo;

    private final IncomeRecordTodo incomeRecordTodo;

    private final IncomeRecordRepository irr;

    private final IncomeRepository ir;

    private final OrderPayRecordRepository oprr;

    private final UserRepository userRepository;

    private final MerchantRepository merchantRepository;

    private final OrderMapper om;

    private final PsUserInComRecordMapper uirm;

    private final SystemMapper systemMapper;

    private final MessageSource messageSource;

    private final WechatPayService wechatPayService;

    private final TransportSettlementRepository transportSettlementRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult buy(MerchantOrderDto para) throws Exception {
        //是否实名认证
        User user=userRepository.findById(para.getUserId()).orElseGet(User::new);
        if(!user.getStatus().equals(AuthenticationStatus.TWO_STATUS)){
            return new BaseResult(11, messageSource.getMessage("BuyUserOrderServiceImpl.buy.status", null, Locale.CHINA));
        }
        MerchantCoal coal = merchantCoalRepository.findById(para.getMerchantCoalId()).orElseGet(MerchantCoal::new);
        if(System.currentTimeMillis()>coal.getOverTime().getTime()){
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.buy.over", null, Locale.CHINA));
        }

        //判断剩余煤炭数量是否足够
        if (coal.getCoalNumber().compareTo(para.getNumber()) == -1) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.buy.compareTo", null, Locale.CHINA));
        }

        //判断前后台价格是否一致
        BigDecimal price = coal.getSellPrice().multiply(para.getNumber());
        if (price.compareTo(para.getTotalPrice()) != 0) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.buy.getSellPrice", null, Locale.CHINA));
        }
        //减库存
        BigDecimal nowCoalNumber = coal.getCoalNumber().subtract(para.getNumber());
        BigDecimal oldCoalNumber = coal.getCoalNumber();
        om.updateMerchantCoalNumber(nowCoalNumber, oldCoalNumber, coal.getMerchantCoalId());
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        AddresDto address = systemMapper.selectBysdId(para.getSdId());
        para.setProvince(address.getProvince());
        para.setCity(address.getCity());
        para.setDistrict(address.getDistrict());
        para.setScId(address.getCityId());
        para.setPayType(para.getType());
        para.setSpId(address.getProvinceId());
        para.setCreateTime(new Date());
        para.setBuyUserId(para.getUserId());
        para.setCoalId(coal.getCoalId());
        para.setSellUserId(coal.getUserId());
        para.setMerchantId(coal.getMerchantId());
        para.setSellPrice(coal.getSellPrice());
        para.setPriceUnit(coal.getPriceUnit());
        para.setCoalPrice(coal.getCoalPrice());
        para.setCoalName(coal.getCoalName());
        para.setCoalPic(coal.getCoalPic());
        para.setMerchantName(coal.getMerchantName());
        para.setOrderNo("PO" + CommonUtil.getFourRandom());
        para.setOrderStatus(OrderCommon.STATEUS_ONE);
        para.setCleanWay(OrderCommon.CLEAN_WAY_ONE);
        para.setMineMouthId(coal.getMineMouthId());
        para.setFreight(new BigDecimal(0));
        para.setTotalFreight(new BigDecimal(0));
        para.setAbbreviationAddress(para.getAddress());
        MerchantOrder order = merchantOrderRepository.save(merchantOrderTodo.toEntity(para));
        //操作表添加记录
        om.saveOrderRecord(order.getOrderId(), para.getBuyUserId(), OrderCommon.STATEUS_ONE, para.getRemark(), para.getUserName());
        //判断地址在用户地址表是否存在  不存在插入
//        if (para.getUserAddressId() == null) {
//            City city = systemMapper.selectBysdId(para.getSdId());
//            UserAddressDto dto = new UserAddressDto(city.getProvinceId(), city.getCityId(), para.getSdId(), para.getName(), para.getPhone(),
//                    para.getAddress(), para.getIsDefault(), para.getLngX(), para.getLatY());
//            uar.save(uam.toEntity(dto));
//        }


        return new BaseResult(0, order);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult pay(MerchantOrderDto para) throws Exception {
        //查询订单详情
        MerchantOrder order = merchantOrderRepository.findById(para.getOrderId()).orElseGet(MerchantOrder::new);
        //判断订单状态
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_ONE) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.getOrderStatus", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_TWO) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.cancel", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_FOUR) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.refuse", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_FIVE) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.close", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_SIX) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.payment", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_EIGHT) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.delete", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_NINE) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.delete", null, Locale.CHINA));
        }

        if (para.getPayWay().equals(OrderCommon.PAY_WAY_ONE)) {
            //余额支付
            BaseResult result = blanacePay(para, order);
            return result;
        } else if (para.getPayWay().equals(OrderCommon.PAY_WAY_TWO)) {
            //微信支付
            String attach = para.getUserId() + "-" + BillType.BILL_TYPE_ONE + "-" + para.getOrderId();
            //待支付总价
            BigDecimal payMoeny = new BigDecimal(100);

            if (order.getPayType() == 1) {
                // 1煤款+运费
                payMoeny = payMoeny.multiply(order.getTotalFreight().add(order.getTotalPrice()));
            }
            if (order.getPayType() == 2) {
                //、2煤款
                payMoeny = payMoeny.multiply(order.getTotalPrice());
            }
            if (order.getPayType() == 3) {
                //、3运费
                payMoeny = payMoeny.multiply(order.getTotalFreight());
            }
            Integer waitPayMoeny = payMoeny.intValue();
            return new BaseResult(0, wechatPayService.unifiedorder("订单费用支付", waitPayMoeny, attach, "APP", ""));
        }
        return new BaseResult(1,messageSource.getMessage("BuyUserOrderServiceImpl.pay.type", null, Locale.CHINA));
    }

    private BaseResult blanacePay(MerchantOrderDto para, MerchantOrder order) {
        //判断支付密码
        User users = userRepository.findById(para.getUserId()).orElseGet(User::new);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        if (!bCryptPasswordEncoder.matches(para.getPayPass(), users.getPayPass())) {
            return new BaseResult(5, messageSource.getMessage("BuyUserOrderServiceImpl.pay.getPayPass", null, Locale.CHINA));
        }
        if (!users.getEnabled()) {
            //说明用户被禁用
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.getEnabled", null, Locale.CHINA));
        }


        // 1煤款+运费、2煤款、3运费
        //计算费用
        BigDecimal needPayMoeny = new BigDecimal(0);
        if (order.getPayType().longValue() == OrderCommon.PAY_TYPE_ONE) {
            needPayMoeny = order.getTotalFreight().add(order.getTotalPrice());
        }
        if (order.getPayType().longValue() == OrderCommon.PAY_TYPE_TWO) {
            needPayMoeny = order.getTotalPrice();
        }
        if (order.getPayType().longValue() == OrderCommon.PAY_TYPE_THREE) {
            needPayMoeny = order.getTotalFreight();
        }
        //判断可用余额是否足够
        Income user = ir.findByUserId(para.getUserId());
        //不足提示充值金额
        if (user.getUsableBlanace().compareTo(needPayMoeny) == -1) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.pay.getUsableBlanace", null, Locale.CHINA));
        }

        //扣除用户余额
        BigDecimal nowBlanace = user.getUsableBlanace().subtract(needPayMoeny);
        BigDecimal userNowAccountBlanace = user.getAccountBlanace().subtract(needPayMoeny);
        uirm.updateBlanace(user.getUsableBlanace(), nowBlanace,  para.getUserId(),user.getAccountBlanace(),userNowAccountBlanace);
        //用户余额记录表(ps_income_record)添加记录
        String billNo = "PB" + CommonUtil.getFourRandom();

        //订单支付记录表添加数据
        OrderPayRecord payRecord = oprr.save(new OrderPayRecord(para.getOrderId(), OrderCommon.PAY_WAY_ONE, needPayMoeny, para.getUserId(), new Date()));

        //账单表添加数据
        Merchant merchant= merchantRepository.findById(order.getMerchantId()).orElseGet(Merchant::new);
        IncomeRecordDto record = new IncomeRecordDto(user.getUserId(), billNo, needPayMoeny, OrderCommon.PAYMENT_TYPE_TWO, OrderCommon.BILL_TYPE_ONE,
                order.getOrderId(),
                OrderCommon.PAY_WAY_ONE, "余额支付煤款", 1, new Date(),1,merchant.getName(),merchant.getDoorImg(),payRecord.getOrderPayRecordId());
        irr.save(incomeRecordTodo.toEntity(record));


        //更新订单表状态
        order.setPayWay(OrderCommon.PAY_WAY_ONE);
        order.setFreighWay(OrderCommon.PAY_WAY_ONE);
        order.setOrderWay(OrderCommon.PAY_WAY_ONE);
        order.setPayTotalFreight(para.getTotalFreight());
        order.setPayTotalPrice(para.getTotalPrice());
        order.setOrderStatus(OrderCommon.STATEUS_SIX);
        order.setPayTime(new Date());
        merchantOrderRepository.save(order);
        //更新用户余额
        PayResult result = new PayResult(needPayMoeny);

        //用户通知
        OosPush.push("付款通知","您的账户支出"+needPayMoeny+"元","ALIAS", users.getAlias());
        //商户通知
        User sellUser=userRepository.findById(order.getSellUserId()).orElseGet(User::new);
        OosPush.push("支付通知","您的订单被支付"+needPayMoeny+"元","ALIAS", sellUser.getAlias());
        return new BaseResult(0, result);
    }

    @Override
    public BaseResult selectUserOrderList(MerchantOrderDto para) {
        int page = (para.getPage()) * para.getSize();
        List<MerchantOrderDto> list = om.selectUserOrderList(para.getUserId(), para.getType(), page < 0 ? 0 : page, para.getSize());
        return new BaseResult(0, list);
    }

    @Override
    public BaseResult orderDetil(MerchantOrderDto para) {
        MerchantOrderDto order = om.orderDetil(para.getOrderId());
        return new BaseResult(0, order);
    }


    @Override
    public BaseResult allcity() {
        return new BaseResult(0, om.selectAllProvice());
    }

    @Override
    public BaseResult updateAddress(MerchantOrderDto para) {
        MerchantOrder order = merchantOrderRepository.findById(para.getOrderId()).orElseGet(MerchantOrder::new);
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_TWO) {
            return new BaseResult(1,  messageSource.getMessage("BuyUserOrderServiceImpl.updateAddress.OrderStatus", null, Locale.CHINA));
        }
        if (order.getOrderStatus().longValue() == OrderCommon.STATEUS_SEVEN) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.updateAddress.longValue", null, Locale.CHINA));
        }
        AddresDto address = systemMapper.selectBysdId(para.getSdId());
        order.setProvince(address.getProvince());
        order.setCity(address.getCity());
        order.setDistrict(address.getDistrict());
        order.setScId(address.getCityId());
        order.setSpId(address.getProvinceId());
        order.setSdId(para.getSdId());
        order.setLatY(para.getLatY());
        order.setLngX(para.getLngX());
        order.setName(para.getName());
        order.setPhone(para.getPhone());
        order.setAddress(para.getAddress());
        order.setAbbreviationAddress(order.getAddress());
        merchantOrderRepository.save(order);
        return new BaseResult(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult sureDelivery(MerchantOrderDto para) {
        MerchantOrder order = merchantOrderRepository.findById(para.getOrderId()).orElseGet(MerchantOrder::new);
        //订单状态(1已下单,2用户取消,3商户确认,4商户拒绝，5关闭（24小时），6已支付，7商家提现收货)
        if (order.getOrderStatus().longValue() != OrderCommon.STATEUS_SEVEN) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.sureDelivery.getOrderStatus", null, Locale.CHINA));
        }
        //更新订单状态
        order.setOrderStatus(OrderCommon.STATEUS_TEN);
        order.setOverTime(new Date());
        merchantOrderRepository.save(order);

        //记录表添加数据
        om.saveOrderRecord(para.getOrderId(), para.getUserId(), OrderCommon.STATEUS_TEN, "买家确认", para.getUserName());
        //未运输的数量
        BigDecimal notTransportNumber=order.getNumber();
        //剩余运费
        BigDecimal downFee=order.getTotalFreight();
        //应退运费
        BigDecimal backFee=new BigDecimal(0);
        //差异煤款
        BigDecimal diffPrice=new BigDecimal(0);

        if(order.getPayType()==1){
            //判断运费差距、
            //查询已经运到的数量
            List<TransportSettlement> settlements=transportSettlementRepository.findByOrderIdAndStatus(para.getOrderId(),3);
            for (TransportSettlement st : settlements) {
                diffPrice=diffPrice.add(st.getDiffPrice());
                downFee=downFee.subtract(st.getTotalPrice());
                //当实收吨位大于矿发吨位时则以矿发吨位结算，两者取其小
                notTransportNumber=notTransportNumber.subtract(st.getArrivalNum().compareTo(st.getMineHairNum())==1?st.getMineHairNum():st.getArrivalNum());
            }
            backFee=notTransportNumber.multiply(order.getFreight());
        }
        //应退煤款
        BigDecimal backCoalFee=notTransportNumber.multiply(order.getSellPrice());
        //
        //商家应得款项  等于 总煤款减去 应退煤款 加 （剩余运费减去应退运费） + 差异煤款
        BigDecimal   merchantFee=order.getTotalPrice().subtract(backCoalFee).add((downFee.subtract(backFee)));
        merchantFee=merchantFee.add(diffPrice);
        //用户应退费用  等于 应退煤款加 应退运费
        BigDecimal  userFee=backFee.add(backCoalFee);

        User buyUser=userRepository.findById(order.getBuyUserId()).orElseGet(User::new);
        User sellUser=userRepository.findById(order.getSellUserId()).orElseGet(User::new);
        String billNo = "PB" + CommonUtil.getFourRandom();
        //商家账单表添加数据
        IncomeRecordDto record = new IncomeRecordDto(order.getSellUserId(), billNo, merchantFee, OrderCommon.BPAYMENT_TYPE_ONE, OrderCommon.BILL_TYPE_THREE,
                order.getOrderId(), OrderCommon.PAY_WAY_FIVE, "订单结算煤款", 1, new Date(),1
                ,buyUser.getName(),buyUser.getAvatarName(),null);
        irr.save(incomeRecordTodo.toEntity(record));
        //更新商家余额
        Income sellIncome=ir.findByUserId(order.getSellUserId());
        BigDecimal merchantNowBlanace = sellIncome.getUsableBlanace().add(merchantFee);
        BigDecimal merchantNowAccountBlanace = sellIncome.getAccountBlanace().add(merchantFee);
        uirm.updateBlanace(sellIncome.getUsableBlanace(), merchantNowBlanace,  sellIncome.getUserId(),sellIncome.getAccountBlanace(),merchantNowAccountBlanace);
        //商家消息通知
        OosPush.push("到账通知","您的账户收入"+merchantFee+"元","ALIAS", sellUser.getAlias());
        if(userFee.compareTo(BigDecimal.ZERO)==1){
            Income buyUserIncome=ir.findByUserId(order.getBuyUserId());
            //用户账单表添加数据
            Merchant merchant= merchantRepository.findById(order.getMerchantId()).orElseGet(Merchant::new);
            IncomeRecordDto records = new IncomeRecordDto(order.getBuyUserId(), billNo, userFee, OrderCommon.BPAYMENT_TYPE_ONE, OrderCommon.BILL_TYPE_SENVEN,
                    order.getOrderId(), OrderCommon.PAY_WAY_FIVE, "订单结算退款", 1, new Date(),1
                    ,merchant.getName(),merchant.getDoorImg(),null);
            irr.save(incomeRecordTodo.toEntity(records));
            //更新用户余额
            BigDecimal userNowBlanace = buyUserIncome.getUsableBlanace().add(userFee);
            BigDecimal userNowAccountBlanace = buyUserIncome.getAccountBlanace().add(userFee);
            uirm.updateBlanace(buyUserIncome.getUsableBlanace(), userNowBlanace,  buyUserIncome.getUserId(),buyUserIncome.getAccountBlanace(),userNowAccountBlanace);
            //用户通知
            OosPush.push("退款通知","您的账户收入"+userFee+"元","ALIAS", buyUser.getAlias());
        }
        return new BaseResult(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult delete(MerchantOrderDto para) {
        MerchantOrder order = merchantOrderRepository.findById(para.getOrderId()).orElseGet(MerchantOrder::new);
        if (order.getOrderStatus().equals(OrderCommon.STATEUS_EIGHT)) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.delete.OrderCommon", null, Locale.CHINA));
        }
        if (!order.getOrderStatus().equals(OrderCommon.STATEUS_TWO) && !order.getOrderStatus().equals(OrderCommon.STATEUS_FOUR) && !order.getOrderStatus().equals(OrderCommon.STATEUS_TEN)) {
            return new BaseResult(1, messageSource.getMessage("BuyUserOrderServiceImpl.delete.status", null, Locale.CHINA));
        }
        order.setOrderStatus(OrderCommon.STATEUS_EIGHT);
        merchantOrderRepository.save(order);
        om.saveOrderRecord(para.getOrderId(), para.getUserId(),OrderCommon.STATEUS_EIGHT, "买家删除", para.getUserName());
        return new BaseResult(0,messageSource.getMessage("MerchantOrderServiceImpl.update.delete.success", null, Locale.CHINA));
    }


}
